package io.hellsinger.vortex.ui.component.adapter

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

abstract class SingleTypeAdapter<T, VH : ViewHolder> : RecyclerView.Adapter<VH>() {
    protected val list = mutableListOf<T>()
    protected val scope =
        CoroutineScope(Dispatchers.Main.immediate + CoroutineName("Single Adapter scope") + SupervisorJob())

    fun replace(data: List<T>) =
        scope.launch {
            if (data == list) return@launch

            if (data.isEmpty()) {
                val count = itemCount
                list.clear()
                notifyItemRangeRemoved(0, count)
                return@launch
            }

            val differ =
                createDiffer(data) ?: run {
                    list.clear()
                    list.addAll(data)
                    notifyDataSetChanged()
                    return@launch
                }
            val result =
                withContext(Dispatchers.Default) {
                    val result = DiffUtil.calculateDiff(differ)
                    list.clear()
                    list.addAll(data)
                    result
                }

            result.dispatchUpdatesTo(this@SingleTypeAdapter)
        }

    protected abstract fun createDiffer(new: List<T>): DiffUtil.Callback?

    protected abstract fun createViewHolder(parent: ViewGroup): VH

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int,
    ): VH = createViewHolder(parent)

    override fun getItemCount(): Int = list.size

    operator fun get(index: Int): T = list[index]
}
